#include <compilation/Function.h>


namespace compilation
{

void
Function::setDominationFrontier(void)
{
  std::vector<VirtualInstruction*>::const_iterator iter =
      m_instructions.begin();
  for (; iter != m_instructions.end(); ++iter)
  {
    if ((*iter)->type() == InstructionType::TLabel)
    {
      LabelInstruction const& label =
          *instruction_cast<TLabel>(*iter);

      // Manage predecessor comming from m_goto (then part).
      if (label.getGoto())
      {
        VirtualInstruction* notDominator = label.getGoto();
        while (notDominator != label.getSDominator())
        {
          assert(notDominator->getSPreviousInstruction());
          while (notDominator->type() != InstructionType::TLabel &&
                 notDominator->getSPreviousInstruction()->type() !=
                 InstructionType::TIf)
          {
            notDominator = notDominator->getSPreviousInstruction();
            assert(notDominator->getSPreviousInstruction());
          }

          // If reaching the end of an included if-then-else.
          if (notDominator->type() == InstructionType::TLabel)
          {
            LabelInstruction& labelInstruction =
                instruction_cast<TLabel>(*notDominator);

            labelInstruction.addDominationFrontier(*label.getGoto());

            // Jump to the dominator of the current node. [*]
            notDominator = labelInstruction.getSDominator();
          }

          // Come here after a label jump (cf. [*]) or just
          // before reaching label.m_dominator.
          if (notDominator->getSPreviousInstruction()->type() ==
              InstructionType::TIf)
          {
            instruction_cast<TGoto>(*notDominator)
                .addDominationFrontier(*label.getGoto());

            notDominator = notDominator->getSPreviousInstruction();
          }
        }
      }

      // Manage the direct predecessor (else part).
      if (label.getSPreviousInstruction())
      {
        VirtualInstruction* notDominator =
            label.getSPreviousInstruction();
        GotoInstruction* origin =
            instruction_cast<TGoto>(notDominator);

        while (label.getSDominator() != notDominator)
        {
          assert(notDominator->getSPreviousInstruction());
          while (notDominator->type() != InstructionType::TLabel &&
                 notDominator->getSPreviousInstruction()->type() !=
                 InstructionType::TIf)
          {
            notDominator = notDominator->getSPreviousInstruction();
            assert(notDominator->getSPreviousInstruction());
          }

          // If reaching the end of an included if-then-else.
          if (notDominator->type() == InstructionType::TLabel)
          {
            LabelInstruction& labelInstruction =
                instruction_cast<TLabel>(*notDominator);

            labelInstruction.addDominationFrontier(*origin);

            // Jump to the dominator of the current node. [**]
            notDominator = labelInstruction.getSDominator();
          }

          // Come here after a label jump (cf. [**]) or just
          // before reaching label.m_dominator.
          if (notDominator->getSPreviousInstruction()->type() ==
              InstructionType::TIf)
          {
            instruction_cast<TGoto>(*notDominator)
                .addDominationFrontier(
                  instruction_cast<TGoto>(
                    *label.getSPreviousInstruction()));

            notDominator = notDominator->getSPreviousInstruction();
          }
        }
      }
    }
  }
}


} // compilation
